var _gl = require('opengl');
var _geometry = require('core/glm.js');
var _glm = _geometry.glm;
var _v3 = _geometry.vec3f;
var _matrix4 = _geometry.matrix4;
var _createStructor = require('glcore/meshbuffer.js').createStructor;
var _createMesh = require('glcore/meshbuffer.js').createMesh;
var _Buffer = require('glcore/buffer.js').Buffer;
var _Filler = require('drawable/framefiller.js');

var EDGE_WIDTH = 10;

function EdgeElement(inner, outer, edge) {
    this.inner = inner;
    this.outer = outer;
    this.edge = edge;
}

function Outline(frame) {
    this.mFrame = frame;
    this.mWidth = frame.width();

    this.mMatrix = new _matrix4();

    this.mZ = new _v3(0, 0, 1);
    this.mPoint = new (_createStructor('p3t2'))();
    this.mFiller = _Filler.createFiller(this.mPoint, frame);

    this.mEdges = [];
    for (var i = 0; i < 4; i++) {
        this.mEdges.push(new EdgeElement());
    }
    this.initElements();
}
Outline.prototype.createBuffer = function (points) {
    return new _Buffer({
        stride: this.mPoint.byteLength,
        count: points,
        type: Int8Array,
        normalize: false
    });
};
Outline.prototype.createGLBuffer = function (points) {
    return _createMesh('p3t2', points, _gl.TRIANGLES);
};
Outline.prototype.initElements = function () {
    this.initElement();// original

    var c = this.mWidth / 2;
    var e0 = this.mEdges[0];
    for (var i = 1; i < 4; i++) {
        this.mMatrix.identity();
        this.mMatrix.translate(c, c);
        this.mMatrix.rotate(-90 * i, this.mZ);
        this.mMatrix.translate(-c, -c);
        var e = this.mEdges[i];

        this.mFiller.transform(this.mMatrix, e0.outer, 0, e.outer = this.createBuffer(12), 0, 12);
        this.mFiller.transform(this.mMatrix, e0.inner, 0, e.inner = this.createBuffer(12), 0, 12);
        this.mFiller.transform(this.mMatrix, e0.edge, 0, e.edge = this.createBuffer(6), 0, 6);
    }
};
Outline.prototype.initElement = function () {
    var c = this.mWidth / 2;

    this.mMatrix.identity();
    this.mMatrix.rotate(180, this.mZ);
    this.mMatrix.translate(-c, -c);
    this.mFiller.setBuffer(this.mEdges[0].outer = this.createBuffer(12));
    this.mFiller.setMatrix(this.mMatrix);
    this.initOuter();

    this.mMatrix.identity();
    this.mMatrix.rotate(-90, this.mZ);
    this.mMatrix.translate(-c, -c);
    this.mFiller.setBuffer(this.mEdges[0].inner = this.createBuffer(12));
    this.mFiller.setMatrix(this.mMatrix);
    this.initInner();

    this.mMatrix.identity();
    this.mMatrix.rotate(-90, this.mZ);
    this.mMatrix.translate(-c, -c * 2);
    this.mFiller.setBuffer(this.mEdges[0].edge = this.createBuffer(6));
    this.mFiller.setMatrix(this.mMatrix);
    this.initEdge();
};
Outline.prototype.initEdge = function () {
    var h = EDGE_WIDTH;
    var w = this.mWidth;

    var filler = this.mFiller;
    filler.seek(0);
    filler.appendRect(0, 0, w, h);
};
Outline.prototype.initInner = function () {
    var c = this.mWidth / 2;
    var x = c - EDGE_WIDTH;
    var y = c + EDGE_WIDTH;
    var h = this.mWidth;

    var filler = this.mFiller;
    filler.seek(0);
    filler.appendRect(0, c, x, y);
    filler.appendRectV(x, c, c, h);
};
Outline.prototype.initOuter = function () {
    var c = this.mWidth / 2;
    var h = this.mWidth;
    var x = c + EDGE_WIDTH;
    var y = c - EDGE_WIDTH;

    var filler = this.mFiller;
    filler.seek(0);
    filler.appendRect(0, y, c, c);
    filler.appendRectV(c, y, x, h);
};
/**
 * @param offset
 * @param edge
 * @param buffer mesh buffer
 * @param index
 * @returns {number} new index
 */
Outline.prototype.appendInner = function (offset, edge, buffer, index) {
    _glm.translation(this.mMatrix, offset);
    this.mFiller.transform(this.mMatrix, this.mEdges[edge].inner, 0, buffer, index, 12);
    return index + 12;
};
Outline.prototype.appendOuter = function (offset, edge, buffer, index) {
    _glm.translation(this.mMatrix, offset);
    this.mFiller.transform(this.mMatrix, this.mEdges[edge].outer, 0, buffer, index, 12);
    return index + 12;
};
Outline.prototype.appendLine = function (offset, edge, buffer, index) {
    _glm.translation(this.mMatrix, offset);
    this.mFiller.transform(this.mMatrix, this.mEdges[edge].edge, 0, buffer, index, 6);
    return index + 6;
};

module.exports = Outline;